<?php
/**
 * DMFramework
 * 
 * @license Copyright 2012 Dillen Meijboom under the Apache license version 2.0 (http://apache.org/licenses/LICENSE-2.0)
 * @author Dillen Meijboom <info@dillenm.nl>
 * @url http://dmframework.nl
 */

/**
 * The database authentication class.
 * 
 * @license Copyright 2012 Dillen Meijboom under the Apache license version 2.0 (http://apache.org/licenses/LICENSE-2.0)
 * @author Dillen Meijboom <info@dillenm.nl>
 * @package System.Library.Auth
 */
class Dmf_Auth_Db
{
    /**
     * Db adapter
     * 
     * @var Dmf_Db_Adapter 
     */
    private $_dbAdapter;
    
    /**
     * Username column
     * 
     * @var string 
     */
    private $_username = 'username';
    
    /**
     * Id column
     * 
     * @var string 
     */
    private $_id = 'id';
    
    /**
     * Password column
     * 
     * @var string
     */
    private $_password = 'password';
    
    /**
     * Table name
     * 
     * @var string 
     */
    private $_table = 'users';
    
    /**
     * Salt used for encryption
     * 
     * @var mixed
     */
    private $_salt = false;
    
    /**
     * Encryption type
     * 
     * @var mixed
     */
    private $_encryption = false;
    
    /**
     * Max attempts
     * 
     * @var int 
     */
    private $_maxAttempts = 0;
    
    /**
     * Login attempts so far
     * 
     * @var int
     */
    private $_attempts;
    
    /**
     * Only set when attempts is needed
     * 
     * @var Dmf_Sessions|null
     */
    private $_sessions;
    
    /**
     * Constructor
     * 
     * @param Dmf_Db_Adapter $dbAdapter 
     */
    public function __construct( Dmf_Database_Adapter_Abstract $dbAdapter, $sessions = false )
    {
        $this->_dbAdapter = $dbAdapter;
        
        if ( $sessions instanceof Dmf_Sessions )
        {
            $this->_sessions = $sessions;
            $this->_attempts = ( $sessions->read( 'login_attempts' ) == null ? 0 : $sessions->read( 'login_attempts' ) );
        }
    }
    
    /**
     * Max login attempts reached?
     * 
     * @return boolean
     */
    public function isMaxAttempts()
    {
        return ( $this->_attempts >= $this->_maxAttempts && $this->_attempts !== null ) ? true : false;
    }
    
    /**
     * Set max attempts
     * 
     * @param int $attemps 
     */
    public function loginAttempts( $attemps )
    {
        $this->_maxAttempts = $attemps;
    }
    
    /**
     * Set identity column
     * 
     * @param string $id
     * @return Dmf_Auth 
     */
    public function setIdentity( $id )
    {
        $this->_id = $id;
        
        return $this;
    }
    
    /**
     * Set username column
     * 
     * @param string $username
     * @return Dmf_Auth 
     */
    public function setUsername( $username )
    {
        $this->_username = $username;
        
        return $this;
    }
    
    /**
     * Set password column
     * 
     * @param string $password
     * @return Dmf_Auth 
     */
    public function setPassword( $password )
    {
        $this->_password = $password;
        
        return $this;
    }
    
    /**
     * Set encryption type
     * 
     * @param string $enc
     * @param string $salt
     * @return Dmf_Auth 
     */
    public function setEncryption( $enc, $salt )
    {
        $this->_encryption = $enc;
        $this->_salt = $salt;
        
        return $this;
    }
    
    /**
     * Set table name
     * 
     * @param string $table
     * @return Dmf_Auth 
     */
    public function setTable( $table )
    {
        $this->_table = $table;
        
        return $this;
    }
    
    /**
     * Get identity value
     * 
     * @return int 
     */
    public function getId()
    {
        return $this->_idValue;
    }
    
    /**
     * Hash text
     * 
     * @param string $encrypt
     * @param string $string 
     */
    public function hash( $encrypt, $string )
    {
        if ( $encrypt == 'sha512' )
        {
            return hash( 'sha512', $string );
        }
    }
    
    /**
     * Add login attempt 
     */
    private function _addAttempt()
    {
        $this->_attempts++;
    }
    
    /**
     * Clear login attempts 
     */
    private function _clearAttempts()
    {
        $this->_attempts = 0;
    }
    
    /**
     * Validate login data
     * 
     * @param string $data
     * @return boolean 
     */
    public function validate( $username, $password )
    {
        $data = array(
            'username' => $username,
            'password' => $password
        );
        
        $password = ( $this->_encryption === false ) ? $data['password'] : $this->hash( $this->_encryption, $this->_salt . $data['password'] );
        
        $result = $this->_dbAdapter->fetchRow( 
            "SELECT `" . $this->_id . "` FROM `" . $this->_table . "` WHERE `" . $this->_username . "`=? AND `" . $this->_password . "`=?",
            $data['username'],
            $password
        );
        
        if ( $result !== false && is_array( $result ) )
        {
            $this->_idValue = $result[ $this->_id ];
            
            $this->_clearAttempts();
            
            return true;
        }
        else
        {
            $this->_addAttempt();
            
            return false;
        }
    }
    
    /**
     * Clear all attempts 
     */
    public function __destruct()
    {
        if ( $this->_sessions instanceof Dmf_Sessions )
        {
            $this->_sessions->write( 'login_attempts', $this->_attempts );
        }
    }
}